package com.yms.socket.client;

import com.alibaba.fastjson.JSONObject;
import com.yms.socket.SelectorUtil;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Scanner;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @version : 1.0
 * @author: yangmingsong
 * @date: 2022/7/20-07-20-15:24
 * @description: spring5Test NIO的相关实现，创建客户端 ，客户端可创建多个
 */
public class NIOClient {


    public static void main(String[] args) throws IOException {
        ExecutorService threadPool = Executors.newFixedThreadPool(3);
        CompletableFuture.runAsync(()->{
            try {
                createClient();
            } catch (IOException e) {
            }},threadPool);
        CompletableFuture.runAsync(()->{
            try {
                createServer();
            } catch (IOException e) {
                e.printStackTrace();
            }
        },threadPool);
    }

    private static void createClient() throws IOException {
        //客户端channel绑定端口号和IP
        SocketChannel channel = null;
        while (true){
            try {
                channel = SocketChannel.open(new InetSocketAddress("127.0.0.1",8089));
                System.out.println("=======客户端已链接========");
                break;
            } catch (IOException e) {
                System.out.println("=========客户端正在尝试链接====请稍等=======");
            }
        }
        channel.configureBlocking(false);
        while (!channel.finishConnect()){}
        Scanner scanner = new Scanner(System.in);
        while (scanner.hasNext()){
            ByteBuffer buffer = ByteBuffer.allocate(1024 *1024);
            String s = scanner.next();
            buffer.put(s.getBytes());
            buffer.flip();
            //调用write方法，将缓存区的数据写入通道，那么就是相当于读取缓存区的数据，因此使用前需将缓存区反转
            channel.write(buffer);
            buffer.clear();
        }
    }
    public static void createServer() throws IOException{
        ServerSocketChannel channel = ServerSocketChannel.open();
        channel.configureBlocking(false);
        Selector selector = Selector.open();
        channel.bind(new InetSocketAddress(8099));
        channel.register(selector, SelectionKey.OP_ACCEPT);
        while (selector.select() > 0) {
            Set<SelectionKey> keys = selector.selectedKeys();
            Iterator<SelectionKey> iterator = keys.iterator();
            while (iterator.hasNext()){
                SelectionKey selectionKey = iterator.next();
                if (selectionKey.isAcceptable()) {
//                        如果选择键的IO事件是连接就绪就获取客户端链接
                    SocketChannel accept = channel.accept();
                    accept.configureBlocking(false);
                    accept.register(selector,SelectionKey.OP_READ);
                }else if(selectionKey.isReadable()){
                    SocketChannel channel1 = (SocketChannel) selectionKey.channel();
                    ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
                    channel1.read(byteBuffer);
                    byte[] bytes = new byte[byteBuffer.limit()];
                    byteBuffer.flip();
                    for(int i=0;i<byteBuffer.limit();i++){
                        bytes[i] = byteBuffer.get(i);
                    }
                    String string = new String(bytes, "utf-8");
                    System.out.println(string);
                    byteBuffer.clear();
                }
                iterator.remove();
            }
        }
    }



}
